package com.gitee.wsl.platform.thread.task.callback

import com.gitee.wsl.platform.thread.task.TaskExecutor
import com.gitee.wsl.platform.concurrent.api.Cancellable
import com.gitee.wsl.platform.concurrent.api.CancellableForwardRef
import com.gitee.wsl.platform.concurrent.api.MutableCancellable
import com.gitee.wsl.platform.thread.task.bean.Outcome
import org.jetbrains.annotations.ApiStatus

/**
 * INTERNAL API.
 *
 *
 * Continuation objects are used to complete tasks, or for registering
 * [Cancellable] references that can be used to interrupt running tasks.
 *
 *
 * `Continuation` objects get injected in [AsyncFun] functions.
 * See [Task.fromAsync].
 *
 * @param <T> is the type of the value that the task will complete with
</T> */
@ApiStatus.Internal
internal interface Continuation<T> : CompletionCallback<T> {
    /**
     * Returns the [Executor] that the task can use to run its
     * asynchronous computation.
     */
    val executor: TaskExecutor

    /**
     * Registers a [Cancellable] reference that can be used to interrupt
     * a running task.
     *
     * @param cancellable is the reference to the cancellable object that this
     * continuation will register.
     */
    fun registerCancellable(cancellable: Cancellable): Cancellable?

    fun registerForwardCancellable(): CancellableForwardRef

    fun withExecutorOverride(executor: TaskExecutor): Continuation<T>

    fun registerExtraCallback(extraCallback: CompletionCallback<T>)
}

/**
 * INTERNAL API.
 */
@ApiStatus.Internal
internal fun interface AsyncContinuationFun<T> {
    fun invoke(continuation: Continuation<T>)
}

/**
 * INTERNAL API.
 */
@ApiStatus.Internal
internal class CancellableContinuation<T>(
    override val executor: TaskExecutor,
    private val callback: ContinuationCallback<T>,
    private val cancellableRef: MutableCancellable,
) : Continuation<T>, Cancellable {
    constructor(
        executor: TaskExecutor,
        callback: ContinuationCallback<T>,
    ) : this(
        executor,
        callback,
        MutableCancellable()
    )

    override fun cancel() {
        cancellableRef.cancel()
    }

    override fun registerForwardCancellable(): CancellableForwardRef {
        return cancellableRef.newCancellableRef()
    }

    override fun registerCancellable(cancellable: Cancellable): Cancellable? {
        return this.cancellableRef.register(cancellable)
    }

    override fun onOutcome(outcome: Outcome<T>) {
        callback.onOutcome(outcome)
    }

    override fun onSuccess(value: T) {
        callback.onSuccess(value)
    }

    override fun onFailure(e: Throwable) {
        callback.onFailure(e)
    }

    override fun onCancellation() {
        callback.onCancellation()
    }

    override fun withExecutorOverride(executor: TaskExecutor): Continuation<T> {
        return CancellableContinuation<T>(
            executor,
            callback,
            cancellableRef
        )
    }

    override fun registerExtraCallback(extraCallback: CompletionCallback<T>) {
        callback.registerExtraCallback(extraCallback)
    }
}
